<?php

/*
 * CopyRight  : (C)2012-2099 HaoTeam Inc.
 * Document   : Callback.php
 * Created on : 2021-2-5 14:16:48
 * Author     : Tiger <1192851302@qq.com>
 * Description: This is NOT a freeware, use is subject to license terms.
 *              这即使是一个免费软件,使用时也请遵守许可证条款,得到当时人书面许可.
 *              未经书面许可,不得翻版,翻版必究;版权归属 HaoTeam Inc;
 */

namespace app\api\controller\wechat;

use app\Request;
use haoteam\service\EasyWeChatService;
use app\models\Payment;
use app\models\Refunds;

/**
 * 微信回调控制器
 * Class Callback
 * Tiger <1192851302@qq.com> 2021-2-5 14:16:48
 */
class Callback {

    public function __construct() {
        $mid = input('mid', 0);
        Request::macro('mid', function () use ($mid) {
            return $mid ?? 0;
        });
    }

    /**
     * 小程序消息推送
     * @author Tiger <1192851302@qq.com>
     * @param type $mid
     */
    public function app($mid) {
        echo $mid;
    }

    /**
     * 小程序支付回调
     * @author Tiger <1192851302@qq.com>
     * @param type $mid
     */
    public function payment($mid) {
        $app = EasyWeChatService::payment($mid);
        $response = $app->handlePaidNotify(function ($message, $fail) use($app) {
            $payment = Payment::where('out_trade_no', $message['out_trade_no'])->where('status', 0)->field([
                        'id', 'join_id', 'attach', 'callback', 'callback_status', 'out_trade_no'
                    ])->find();
            if (empty($payment)) {
                return true;
            }
            $_return = $app->order->queryByOutTradeNumber($payment['out_trade_no']);
            trace('WeChat|Callback|payment|' . json_encode($_return), 'debug');
            if ($_return['return_code'] === 'FAIL') {
                trace('WeChat|Callback|payment|查询|通信错误|' . json_encode($_return), 'error');
                return $fail('支付失败，请稍后再通知我');
            }
            if (isset($_return['result_code']) == false || $_return['result_code'] == 'FAIL') {
                trace('WeChat|Callback|payment|查询|业务错误|' . json_encode($_return), 'error');
                //更新支付表
                Payment::update(['transaction_id' => $message['transaction_id'], 'status' => 2, 'pay_time' => date('Y-m-d H:i:s'), 'errDes' => ($_return['err_code'] . $_return['err_code_des'])], ['id' => $payment['id']]);
                return true;
            }
            if (isset($_return['trade_state']) == false || $_return['trade_state'] == 'FAIL') {
                trace('WeChat|Callback|payment|查询|交易错误|' . json_encode($_return), 'error');
                //更新支付表
                Payment::update(['transaction_id' => $message['transaction_id'], 'status' => 2, 'pay_time' => date('Y-m-d H:i:s'), 'errDes' => ($_return['trade_state'] . $_return['trade_state_desc'])], ['id' => $payment['id']]);
                return true;
            }
            try {
                //更新支付表
                Payment::update(['transaction_id' => $message['transaction_id'], 'status' => 1, 'pay_time' => date('Y-m-d H:i:s')], ['id' => $payment['id']]);
                //通知应用
                call_user_func_array(array("{$payment['callback']}", "paySuccess"), compact('message', 'payment'));
            } catch (\Exception $exc) {
                return $fail('支付失败，请稍后再通知我');
            }

            return true;
        });
        return $response->send();
    }

    /**
     * 退款回调
     * @author Tiger <1192851302@qq.com>
     * @param type $mid
     * @return type
     */
    public function refund($mid) {
        $app = EasyWeChatService::payment($mid);
        $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
            trace('WeChat|Callback|refund|退款|' . json_encode($reqInfo), 'debug');
            if ($message['return_code'] === 'FAIL') {
                //return_msg 要不要记录错误信息
                trace('WeChat|Callback|refund|退款失败|' . $message['return_msg'], 'error');
                return true;
            }
            //更新
            Refunds::update(['refund_status' => 1, 'refund_id_no' => $reqInfo['refund_id']], ['refund_order_no' => $reqInfo['out_refund_no']]);
            return true;
        });

        return $response->send();
    }

}
